/**
 * @file bull_hal_drv_uart.c
 * @brief 
 * @author yejing (yejh@gongniu.cn)
 * @version 1.0
 * @date 2024-05-14
 * 
 * Copyright 2024-2025 GongNiu Inc. All Rights Reserved.
 * 
 */

#include "driver/uart.h"
#include "driver/gpio.h"

#include "bull_hal_drv_uart.h"
#include "bull_hal_adapter.h"

#include "bull_hal_sys_semaphore.h"
#include "bull_hal_sys_thread.h"
#include "bull_hal_sys_mutex.h"
#include "bull_hal_config.h"
/***********************************************************
*************************micro define***********************
***********************************************************/

typedef struct
{
    int port;
    SEM_HANDLE    rx_semphr;
    MUTEX_HANDLE  tx_mutex;
    QUEUE_HANDLE  rx_queue;
    THREAD_HANDLE thrd_handle;
} bull_hal_sys_uart_t;

static bull_hal_sys_uart_t uart_ctx[ MAX_HAL_UART_PORTS ] = {
    {0,NULL,NULL,NULL,NULL},
    {0,NULL,NULL,NULL,NULL},
    {0,NULL,NULL,NULL,NULL}
};

typedef struct
{
    int tx_io_num;
    int rx_io_num; 
    int rts_io_num; 
    int cts_io_num;
} bull_hal_drv_uart_t;

static bull_hal_drv_uart_t bull_hal_drv_uart[ MAX_HAL_UART_PORTS ] = {
    { UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE },
    { BULL_UART_TXD1_PIN, BULL_UART_RXD1_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE },
#if ( MAX_HAL_UART_PORTS == 3 )
    { BULL_UART_TXD2_PIN, BULL_UART_RXD2_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE }
#endif
};

/***********************************************************
*************************variable define********************
***********************************************************/



/***********************************************************
*************************function define********************
***********************************************************/



/**
 * @brief 串口接收任务
 * 
 * @param pvParameters 
 */
static void console_uart_task( void *pvParameters )
{
    uart_event_t event;

    bull_hal_sys_uart_t *p_uart = (bull_hal_sys_uart_t*)pvParameters;
    
    for (;;) {
        
        if ( xQueueReceive(p_uart->rx_queue, (void * )&event, (portTickType)portMAX_DELAY) ) {

            switch (event.type) {

                case UART_DATA:
                {
                    //接受到串口数据
                    bull_hal_sys_semaphore_post( p_uart->rx_semphr );
                    
                    break;
                }

                default:
                    break;
            }
        }
    }
    bull_hal_sys_thread_delete(NULL);
}


/**
 * @brief 串口初始化
 * 
 * @param port 串口号
 * @param baud 波特率
 * @return int 
 */
int bull_hal_drv_uart_init( int port, int baud )
{

    if( port > MAX_HAL_UART_PORTS ){

        return OPRT_INVALID_PARM;
    }

    uart_ctx[ port ].port = port;

    uart_config_t uart_config = {
        .baud_rate = baud,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,        
    };

    if( OPRT_OK != uart_driver_install(port, BULL_UART_MAX_RX_BUFFER_SIZE, BULL_UART_MAX_TX_BUFFER_SIZE, 20, (QueueHandle_t *)&(uart_ctx[port].rx_queue), 0) ){

        return OPRT_NOT_INIT;
    }


    if( uart_ctx[port].thrd_handle == NULL ){

        bull_hal_sys_thread_create( console_uart_task,
                            "console_uart_task",
                            2048+512,
                            &uart_ctx[port],
                            8,
                            &(uart_ctx[port].thrd_handle) );
    }

    uart_param_config( port, &uart_config );

    uart_set_pin( port, bull_hal_drv_uart[ port ].tx_io_num, bull_hal_drv_uart[ port ].rx_io_num, bull_hal_drv_uart[ port ].rts_io_num, bull_hal_drv_uart[ port ].cts_io_num );

    // context init
    if ( NULL == uart_ctx[port].rx_semphr ) {

        //申请越大的计数型信号量数值，可以保证压力测试下释放信号量时因为计数不超出而不会导致报错！！！
        if ( OPRT_OK != bull_hal_sys_semaphore_create( &(uart_ctx[port].rx_semphr), 0, 128) ) {

            return OPRT_OS_ADAPTER_SEM_CREAT_FAILED;
        }
    }

    if(NULL == uart_ctx[port].tx_mutex) {

        bull_hal_sys_mutex_create( &(uart_ctx[port].tx_mutex) );
    }

    return OPRT_OK;
}


/**
 * @brief 串口发送数据
 * 
 * @param port 端口号
 * @param buffer 数据
 * @param length 数据长度
 * @return int 返回实际发送的长度
 */
int bull_hal_drv_uart_write( int port, uint8_t* buffer, uint32_t length )
{

    if ( uart_ctx[ port ].port < 0 )
    {
        return -1;
    }
    
    return uart_write_bytes(port,buffer, length);
}


/**
 * @brief 读取数据
 * 
 * @param port 端口号
 * @param buffer 数据
 * @param length 数据长度
 * @param ms 等待数据超时时间
 * @return int 
 */
int bull_hal_drv_uart_read( int port, uint8_t* buffer, uint32_t length, uint32_t ms )
{
    if ( OPRT_OK == bull_hal_sys_semaphore_wait(uart_ctx[port].rx_semphr) ) {

        return uart_read_bytes(port, buffer, length, ms / bull_hal_sys_get_tickratems() );
    }

    return 0;
}

/**
 * @brief 用于释放串口
 * 
 * @param[in]  port     串口句柄
 */
int bull_hal_drv_uart_deinit( int port )
{
    bull_hal_sys_thread_delete( uart_ctx[port].thrd_handle );
    uart_ctx[port].thrd_handle = NULL;

    bull_hal_sys_semaphore_delete( uart_ctx[port].rx_semphr );
    uart_ctx[port].rx_semphr = NULL;
    
    bull_hal_sys_mutex_delete( uart_ctx[port].tx_mutex );
    uart_ctx[port].tx_mutex = NULL;
    
    uart_ctx[ port ].port = -1;

    return uart_driver_delete(port);
}


/**
 * @brief 释放串口的信号量
 * 
 * @param port 
 * @return int 
 */
int bull_hal_drv_uart_block_release( int port )
{
    return bull_hal_sys_semaphore_post( uart_ctx[port].rx_semphr );
}

